diff options
Diffstat (limited to 'app/api/auth/[...nextauth]/route.ts')
| -rw-r--r-- | app/api/auth/[...nextauth]/route.ts | 89 |
1 files changed, 62 insertions, 27 deletions
diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts index 68cc3a5b..fe93906d 100644 --- a/app/api/auth/[...nextauth]/route.ts +++ b/app/api/auth/[...nextauth]/route.ts @@ -89,9 +89,9 @@ let securitySettingsCache: { async function getCachedSecuritySettings() { const now = Date.now() - - if (!securitySettingsCache.data || - (now - securitySettingsCache.lastFetch) > securitySettingsCache.ttl) { + + if (!securitySettingsCache.data || + (now - securitySettingsCache.lastFetch) > securitySettingsCache.ttl) { try { securitySettingsCache.data = await getSecuritySettings() securitySettingsCache.lastFetch = now @@ -102,7 +102,7 @@ async function getCachedSecuritySettings() { } } } - + return securitySettingsCache.data } @@ -110,15 +110,15 @@ async function getCachedSecuritySettings() { function getClientIP(req: any): string { const forwarded = req.headers['x-forwarded-for'] const realIP = req.headers['x-real-ip'] - + if (forwarded) { return forwarded.split(',')[0].trim() } - + if (realIP) { return realIP } - + return req.ip || req.connection?.remoteAddress || '127.0.0.1' } @@ -212,7 +212,7 @@ export const authOptions: NextAuthOptions = { // DB에 로그인 세션 생성 const ipAddress = getClientIP(req) const userAgent = req.headers?.['user-agent'] - + const dbSession = await SessionRepository.createLoginSession({ userId: user.id, ipAddress, @@ -243,7 +243,7 @@ export const authOptions: NextAuthOptions = { } }, }), - + // 1차 인증용 프로바이더 (기존 유지) CredentialsProvider({ id: 'credentials-first-auth', @@ -283,6 +283,7 @@ export const authOptions: NextAuthOptions = { callbacks: { // ✅ JWT callback에 roles 정보 추가 + // JWT callback 수정 async jwt({ token, user, account, trigger, session }) { const securitySettings = await getCachedSecuritySettings() const sessionTimeoutMs = securitySettings.sessionTimeoutMinutes * 60 * 1000 @@ -301,19 +302,50 @@ export const authOptions: NextAuthOptions = { token.authMethod = user.authMethod token.sessionExpiredAt = reAuthTime + sessionTimeoutMs token.dbSessionId = user.dbSessionId - token.roles = user.roles // ✅ roles 정보 추가 + token.roles = user.roles + } + + // ✅ 기존 토큰이 있고 로그인이 아닌 경우, DB에서 최신 사용자 정보 조회 + if (token.id && !user && trigger !== "update") { + try { + const latestUser = await getUserById(parseInt(token.id)) + + if (latestUser) { + // 도메인이 변경되었다면 토큰 업데이트 + if (token.domain !== latestUser.domain) { + console.log(`Domain changed for user ${token.email}: ${token.domain} -> ${latestUser.domain}`) + token.domain = latestUser.domain + } + + // 기타 정보도 최신 상태로 업데이트 + token.name = latestUser.name + token.companyId = latestUser.companyId + token.techCompanyId = latestUser.techCompanyId + + // roles 정보도 최신으로 업데이트 + const userRoles = await getUserRoles(parseInt(token.id)) + token.roles = userRoles + } + } catch (error) { + console.error('Failed to fetch latest user info in JWT callback:', error) + } } // SAML 인증 시 DB 세션 생성 및 roles 조회 if (account && account.provider === 'credentials-saml' && token.id) { const reAuthTime = Date.now() const sessionExpiredAt = new Date(reAuthTime + sessionTimeoutMs) - + try { const numericUserId = ensureNumber(token.id) - - // ✅ SAML 로그인 시에도 roles 정보 조회 - if (!token.roles) { + + // SAML 로그인 시에도 최신 사용자 정보 조회 + const latestUser = await getUserById(numericUserId) + if (latestUser) { + token.domain = latestUser.domain + token.name = latestUser.name + token.companyId = latestUser.companyId + token.techCompanyId = latestUser.techCompanyId token.roles = await getUserRoles(numericUserId) } @@ -323,7 +355,7 @@ export const authOptions: NextAuthOptions = { authMethod: 'saml', sessionExpiredAt, }) - + token.authMethod = 'saml' token.reAuthTime = reAuthTime token.sessionExpiredAt = reAuthTime + sessionTimeoutMs @@ -338,7 +370,7 @@ export const authOptions: NextAuthOptions = { if (session.reAuthTime !== undefined) { token.reAuthTime = session.reAuthTime token.sessionExpiredAt = session.reAuthTime + sessionTimeoutMs - + // DB 세션 업데이트 if (token.dbSessionId) { await SessionRepository.updateLoginSession(token.dbSessionId, { @@ -347,28 +379,31 @@ export const authOptions: NextAuthOptions = { }) } } - + if (session.user) { if (session.user.name !== undefined) token.name = session.user.name if (session.user.email !== undefined) token.email = session.user.email if (session.user.image !== undefined) token.imageUrl = session.user.image + + // ✅ 세션 업데이트 시 도메인 정보도 갱신 가능 + if (session.user.domain !== undefined) token.domain = session.user.domain } } return token - }, - + } +, // ✅ Session callback에 roles 정보 추가 async session({ session, token }: { session: Session; token: JWT }) { // 세션 만료 체크 if (token.sessionExpiredAt && Date.now() > token.sessionExpiredAt) { console.log(`Session expired for user ${token.email}. Expired at: ${new Date(token.sessionExpiredAt)}`) - + // DB 세션 만료 처리 if (token.dbSessionId) { await SessionRepository.logoutSession(token.dbSessionId) } - + return { expires: new Date(0).toISOString(), user: null as any @@ -414,17 +449,17 @@ export const authOptions: NextAuthOptions = { async signIn({ user, account, profile }) { const securitySettings = await getCachedSecuritySettings() console.log(`User ${user.email} signed in via ${account?.provider} (authMethod: ${user.authMethod}), session timeout: ${securitySettings.sessionTimeoutMinutes} minutes`); - + // 이미 MFA에서 DB 세션이 생성된 경우가 아니라면 여기서 생성 if (account?.provider !== 'credentials-mfa' && user.id) { try { const numericUserId = ensureNumber(user.id) - + // 기존 활성 세션 확인 const existingSession = await SessionRepository.getActiveSessionByUserId(numericUserId) if (!existingSession) { const sessionExpiredAt = new Date(Date.now() + (securitySettings.sessionTimeoutMinutes * 60 * 1000)) - + await SessionRepository.createLoginSession({ userId: numericUserId, ipAddress: '0.0.0.0', @@ -437,14 +472,14 @@ export const authOptions: NextAuthOptions = { } } }, - + async signOut({ session, token }) { console.log(`User ${session?.user?.email || token?.email} signed out`); - + // DB에서 세션 로그아웃 처리 const userId = session?.user?.id || token?.id const dbSessionId = session?.user?.dbSessionId || token?.dbSessionId - + if (dbSessionId) { await SessionRepository.logoutSession(dbSessionId) } else if (userId) { |
